<?php
    defined('M2_MICRO') or die('Direct Access to this location is not allowed.');

    /**
      * @desc Class for handling errors
      * @package M2 Micro Framework
      * @author Alexander Chaika
      */
    class Error {
        // instance
        private static $instance = null;
        
        protected $_error_msg;
        protected $_last_result;

        /**
          * Error class constructor & clone
          * Use pattern singleton
          */
        private function __construct() {}
        private function __clone() {}

        /**
          * Return the instance of object
          * @param array $config (optional)
          */
        public static function getInstance() {
            // clear stack
            unset($_SESSION['error_stack']);
            unset($_SESSION['messages_stack']);

            // return instance
            if (null === self::$instance) {
                self::$instance = new self();
            }
            return self::$instance;
        }

        /**
          * Get last error message
          * @return string $error
          */
        public function getError() {
            return $this->_error_msg;
        }

        /**
          * Get last result number (count returned or updated rows)
          * if $count < 0, we have error
          * @return int $count
          */
        public function getLastResult() {
            return $this->_last_result;
        }

        /**
          * Trow error
          * @return bool FALSE
          */
        public function throwError($error_msg, $error_num = -1) {
            // add message to global error stack
            $this->addToErrorStack($error_msg, $error_num);

            // set message to current object
            $this->_last_result = $error_num;
            $this->_error_msg = $error_msg;

            // $this->logError();
            return false;
        }

        /**
          * Clean error
          * @return bool FALSE
          */
        protected function cleanError($message = null) {
            // add message to global messages stack
            if (!empty($message)) $this->addToMessagesStack($message);

            // clean errors
            $this->_last_result = 1;
            $this->_error_msg = '';

            return true;
        }

        /**
          * Put to file error
          * @return bool $state
          */
        protected function logError() {
            $filename = 'error.log';
            $string = date('c') . ': [' . $this->_last_result . '] ' . $this->_error_msg . chr(13) . chr(10);

            if (is_writable($filename)) {
                $handle = fopen($filename, 'a+');
                if (!$handle) return false;
                if (!fwrite($handle, $string)) return false;
                fclose($handle);
            } else {
                $handle = fopen($filename, 'w');
                if (!$handle) return false;
                if (!fwrite($handle, $string)) return false;
                fclose($handle);
            }
            return true;
        }

        /**
          * Put message to error stack
          * @return int $index
          */
        public function addToErrorStack($error_msg, $error_num = null){
            if (empty($_SESSION['error_stack'])) $_SESSION['error_stack'] = array();
            return array_unshift($_SESSION['error_stack'], $error_msg);
        }

        /**
          * Put message to messages stack
          * @return int $index
          */
        public function addToMessagesStack($message){
            if (empty($_SESSION['messages_stack'])) $_SESSION['messages_stack'] = array();
            return array_unshift($_SESSION['messages_stack'], $message);
        }

        /**
          * Return error stack
          * @return array $stack
          */
        public function getErrorStack() {
            return $_SESSION['error_stack'];
        }

        /**
          * Get last message from stack
          * @return string $message
          */
        public function getLastErrorFromStack() {
            if (empty($_SESSION['error_stack'])) $_SESSION['error_stack'] = array();
            return (count($_SESSION['error_stack']) > 0 ? $_SESSION['error_stack'][0] : 'Unknown exception!');
        }
        
        /**
          * Return messages stack
          * @return array $stack
          */
        public function getMessagesStack() {
            return $_SESSION['messages_stack'];
        }

        /**
          * Get last message from stack
          * @return string $message
          */
        public function getLastMessageFromStack() {
            if (empty($_SESSION['messages_stack'])) $_SESSION['messages_stack'] = array();
            return (count($_SESSION['messages_stack']) > 0 ? $_SESSION['messages_stack'][0] : 'Unknown exception!');
        }

        /**
          * Check error stack
          * @return bool $state
          */
        public function isPresent() {
            if (empty($_SESSION['error_stack'])) return false;
            else return true;
        }

        /**
          * Clean all stacks
          */
        public function cleanAll() {
            unset($_SESSION['error_stack']);
            unset($_SESSION['messages_stack']);
            return;
        }
    }

    // global object
    $GLOBALS['error'] = Error::getInstance();
?>
